/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved.  This code is subject to the terms
 * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */

package apidemo;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;


import apidemo.AccountInfoPanel.Table;
import apidemo.util.HtmlButton;
import apidemo.util.VerticalPanel;
import apidemo.util.NewTabbedPanel.NewTabPanel;

import com.ib.client.Order;
import com.ib.controller.ApiController.IAccountHandler;
import com.ib.controller.ApiController.IOrderHandler;
import com.ib.controller.Formats;
import com.ib.controller.NewContract;
import com.ib.controller.NewOrder;
import com.ib.controller.NewOrderState;
import com.ib.controller.OrderStatus;
import com.ib.controller.ApiController.IPositionHandler;
import com.ib.controller.Types.SecType;
import com.ib.controller.Position;


public class PositionsPanel extends NewTabPanel {
	private PositionModel m_model = new PositionModel();
	private boolean m_complete;

	PositionsPanel() {
		HtmlButton sub = new HtmlButton( "Subscribe") {
			protected void actionPerformed() {
				subscribe();
			}
		};
		
		HtmlButton desub = new HtmlButton( "Desubscribe") {
			protected void actionPerformed() {
				desubscribe();
			}
		};

		HtmlButton closePosition = new HtmlButton( "Close Position") {
			protected void actionPerformed() {
				closePosition();
			}
		};

		JPanel buts = new VerticalPanel();
		buts.add( sub);
		buts.add( desub);
		buts.add( closePosition);

		JTable table = new Table( m_model, 2);
		JScrollPane scroll = new JScrollPane( table);
		
		setLayout( new BorderLayout() );
		add( scroll);
		add( buts, BorderLayout.EAST);
	}

	/** Called when the tab is first visited. Sends request for all positions. */
	@Override public void activated() {
		subscribe();
	}

	/** Called when the tab is closed by clicking the X. */
	@Override public void closed() {
		desubscribe();
	}
	
	private void subscribe() {
		ApiDemo.INSTANCE.controller().reqPositions( m_model);
	}
	
	private void desubscribe() {
		ApiDemo.INSTANCE.controller().cancelPositions( m_model);
		m_model.clear();
	}
	
	private void closePosition() {
		//doClosePosition();		
	}
	
	
	private class PositionModel extends AbstractTableModel implements IPositionHandler {
		HashMap<PositionKey,PositionRow> m_map = new HashMap<PositionKey,PositionRow>();
		ArrayList<PositionRow> m_list = new ArrayList<PositionRow>();

		@Override public void position(String account, NewContract contract, int position, double avgCost) {
			PositionKey key = new PositionKey( account, contract.conid() );
			PositionRow row = m_map.get( key);
			if (row == null) {
				row = new PositionRow();
				m_map.put( key, row);
				m_list.add( row);
			}
			row.update( account, contract, position, avgCost);
			
			if (m_complete) {
				m_model.fireTableDataChanged();
			}
		}

		@Override public void positionEnd() {
			m_model.fireTableDataChanged();
			m_complete = true;
		}

		public void clear() {
			m_map.clear();
			m_list.clear();
			fireTableDataChanged();
		}

		@Override public int getRowCount() {
			return m_map.size();
		}

		@Override public int getColumnCount() {
			return 4;
		}
		
		@Override public String getColumnName(int col) {
			switch( col) {
				case 0: return "Account";
				case 1: return "Contract";
				case 2: return "Position";
				case 3: return "Avg Cost";
				default: return null;
			}
		}

		@Override public Object getValueAt(int rowIn, int col) {
			PositionRow row = m_list.get( rowIn);
			
			switch( col) {
				case 0: return row.m_account;
				case 1: return row.m_contract.description();
				case 2: return row.m_position;
				case 3: return Formats.fmt( row.m_avgCost);
				default: return null;
			}
		}
	}
	
	private static class PositionKey {
		String m_account;
		int m_conid;

		PositionKey( String account, int conid) {
			m_account = account;
			m_conid = conid;
		}
		
		@Override public int hashCode() {
			return m_account.hashCode() + m_conid;
		}
		
		@Override public boolean equals(Object obj) {
			PositionKey other = (PositionKey)obj;
			return m_account.equals( other.m_account) && m_conid == other.m_conid;
		}
	}

	private static class PositionRow {
		String m_account;
		NewContract m_contract;
		int m_position;
		double m_avgCost;

		void update(String account, NewContract contract, int position, double avgCost) {
			m_account = account;
			m_contract = contract;
			m_position = position;
			m_avgCost = avgCost;
		}
	}
/*	
	protected void doClosePosition() {
		Contract contract; 
		Position position = m_portfolioModel.getPosition(i);
		//String account = (String)m_accounts.getSelectedValue();
		//onAcctChanged();
		for (int i=0; i<m_model.getRowCount(); i++ ){
			String contract = (String) m_model.getValueAt(i, 2);
			if (contract.substring(2).equals("YM")) {
				Contract contract = m_model.m_list.get(i).m_position;
			}
		}
		
		//int i = m_model.getSelectedRow();
		if (i != -1) {
			if (account != null) {
				
				
				// only call the close orders on futures contracts with open positions
				if ((position.contract().secType() == SecType.FUT) && (position.position() != 0 )) {

					// Create a contract object to reverse the position - use the same contract!
					NewContract order_ticker = position.contract();
	
					// Create an order object
					Order order = new Order() ;
					
					// if we're currently long (signified by a number of contracts > 0) then we need to sell otherwise buy
					if (position.position() > 0 ) {
						order.m_action = "SELL";
					} else if (position.position() < 0 ) {
						order.m_action = "BUY";
					}     
			        order.m_totalQuantity = Math.abs(position.position());
			        order.m_orderType = "MKT";
			        order.m_transmit = true;
			        order.m_referencePriceType = 0;
			        order.m_orderRef = "Auto close position at 3:45am" ;
			        order.m_orderRef = "Auto";
			        order.m_tif = "DAY";
					
			        NewOrder newOrderExecution = new NewOrder(order);
			        
					// Send the Market Order request
					ApiDemo.INSTANCE.controller().placeOrModifyOrder(order_ticker, newOrderExecution, new IOrderHandler() {
	
						@Override
						public void orderState(NewOrderState orderState) {
							ApiDemo.INSTANCE.show("This is the orderState: "
									+ orderState.status().toString());
						}
	
						@Override
						public void handle(int errorCode, String errorMsg) {
							ApiDemo.INSTANCE
									.show("Hey, Error happened for the action: "
											+ errorCode + " " + errorMsg);
						}
	
						@Override
						public void orderStatus(OrderStatus status, int filled,
								int remaining, double avgFillPrice, long permId,
								int parentId, double lastFillPrice, int clientId,
								String whyHeld) {
							// TODO Auto-generated method stub
						}
					});
				} else {
					// nothing to do = no open positions on any future contracts
					ApiDemo.INSTANCE.show("WARNING: Nothing to do - no open positions on any future contracts");
				}
			}
		} else {
			// no position slected error
			ApiDemo.INSTANCE.show("WARNING: Please select a position to close");
		}
	}
}
*/
}
